package com.egg.gateway.filter.secure;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.egg.common.util.SecureUtil;
import com.egg.gateway.service.FeignService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Profile;
import org.springframework.core.Ordered;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Optional;
import java.util.concurrent.Future;

/**
 * 加解密拦截
 *
 * @author east
 */
@Profile({"prod", "test", "dev"})
@Slf4j
@Component
public class AesEncryptDecryptFilter implements GlobalFilter, Ordered {


    @Resource
    ServerCodecConfigurer serverCodecConfigurer;
    @Autowired
    private FeignService feignService;


    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Future<Optional<String>> futureSecure = feignService.aes(exchange.getRequest());
        // 对称秘钥
        Optional<String> aesOpt = futureSecure.get();
        if (!aesOpt.isPresent()) {
            return chain.filter(exchange);
        }
        String aes = aesOpt.get();
        if (ObjectUtil.isEmpty(aes)) {
            return chain.filter(exchange);
        }
        // 修改请求内容
        return new ModifiedRequestDecorator(
                exchange
                , new RewriteConfig().init(String.class, String.class, (ex, requestData)
                // 解密
                -> Mono.justOrEmpty(decrypt(aes, requestData)))
                , serverCodecConfigurer).filter(exchange.mutate().response(
                // 修改响应内容
                new ModifiedResponseDecorator(
                        exchange
                        , new RewriteConfig().init(JSONObject.class, String.class, (ex, responseData)
                        // 加密
                        -> Mono.justOrEmpty(encrypt(aes, responseData)))
                        , serverCodecConfigurer)).build(), chain);
    }

    /**
     * 解密
     *
     * @return
     */
    public static String decrypt(String aes, String requestData) {
        if (ObjectUtil.isEmpty(requestData)) {
            return requestData;
        }
        if (ObjectUtil.isEmpty(aes)) {
            return requestData;
        }
        return SecureUtil.aesDecrypt(aes, requestData);
    }

    /**
     * 加密
     *
     * @return
     */
    private String encrypt(String aes, JSONObject responseData) {
        if (ObjectUtil.isEmpty(responseData)) {
            return null;
        }
        if (ObjectUtil.isEmpty(aes)) {
            return responseData.toString();
        }
        /**
         *  key 跟随包装体中的 数据体 key
         * @see com.egg.common.core.model.response.ResponseData
         */
        Object data = responseData.get("data");
        if (ObjectUtil.isEmpty(data)) {
            return responseData.toString();
        }
        responseData.put("data", SecureUtil.aesEncrypt(aes, data.toString()));
        return responseData.toString();
    }


}